home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2004 #11 / Amiga Plus CD - 2004 - No. 11.iso / AmiSoft / Text / print / HPDJ900Src.lha / compression.c next >
C/C++ Source or Header  |  2004-05-21  |  6KB  |  229 lines

  1. /*
  2.  * $Id: compression.c 44.1 1999/09/02 11:08:00 olsen Exp olsen $
  3.  *
  4.  * :ts=4
  5.  *
  6.  * COPYRIGHT:
  7.  *
  8.  *   Unless otherwise noted, all files are Copyright (c) 1999 Amiga, Inc.
  9.  *   All rights reserved.
  10.  *
  11.  * DISCLAIMER:
  12.  *
  13.  *   This software is provided "as is". No representations or warranties
  14.  *   are made with respect to the accuracy, reliability, performance,
  15.  *   currentness, or operation of this software, and all use is at your
  16.  *   own risk. Neither Amiga nor the authors assume any responsibility
  17.  *   or liability whatsoever with respect to your use of this software.
  18.  *
  19.  */
  20.  
  21. #include "global.h"
  22.  
  23. /*****************************************************************************/
  24.  
  25. LONG StripWhiteSpace(UBYTE * source,LONG size)
  26. {
  27.     LONG i;
  28.  
  29.     /* Optimization: strip all trailing zero bytes. */
  30.     for(i = size ; i > 0 ; i--)
  31.     {
  32.         if(source[i-1] != 0)
  33.         {
  34.             size = i;
  35.             break;
  36.         }
  37.     }
  38.  
  39.     return(size);
  40. }
  41.  
  42. /*****************************************************************************/
  43.  
  44. /* PCL compression method #2, also known as "TIFF packbits" or ByteRun1. */
  45. LONG CompressMethod2(UBYTE * src, UBYTE * dest, LONG count)
  46. {
  47.     UBYTE *    last = dest + count;
  48.  
  49.     UBYTE * outptr;
  50.     UBYTE * inptr;
  51.     UBYTE * saveptr;
  52.  
  53.     UBYTE    data;        /* data byte */
  54.     UBYTE    lastbyte;    /* last byte */
  55.     LONG    repcount;    /* repeat count */
  56.     LONG    litcount;    /* literal count */
  57.  
  58.     inptr = src;
  59.     outptr = dest;
  60.  
  61.     /* Start loop through data. Check for possible repeat at beginning. */
  62.     while(count > 0)
  63.     {
  64.         /* get value to work with */
  65.         data = (*inptr++);
  66.         count--;
  67.  
  68.         /* no repeat count yet */
  69.         repcount = 0;
  70.  
  71.         /* Check for repeat, since we are not in the middle
  72.          * of a literal run, it does not have to be more than
  73.          * two bytes of similar data.
  74.          */
  75.         while(count > 0 && (*inptr) == data)
  76.         {
  77.             repcount++;
  78.             inptr++;
  79.  
  80.             count--;
  81.         }
  82.  
  83.         /* Now, if we are out of data (count == 0), then
  84.          * if the repeated byte was zero, then ignore it
  85.          * completely (don't bother outputing the trailing zeros).
  86.          */
  87.         if(count == 0 && data == 0)
  88.             break; /* done */
  89.  
  90.         /* If there was a repeat (repcount > 0), then we
  91.          * can output the command here, otherwise, we
  92.          * need to go into literal run mode.
  93.          *
  94.          * Note:  This is a while loop because the repeat count
  95.          * may actually be greater than 127.
  96.          */
  97.  
  98.         if(repcount >= 1) /* repeat mode */
  99.         {
  100.             while(repcount > 127)
  101.             {
  102.                 if(outptr + 2 > last)
  103.                     return(-1);
  104.  
  105.                 (*outptr++) = 129;    /* count 127 */
  106.                 (*outptr++) = data;    /* value */
  107.                 repcount -= 128;    /* offset */
  108.             }
  109.  
  110.             if(repcount > 0)
  111.             {
  112.                 if(outptr + 2 > last)
  113.                     return(-1);
  114.  
  115.                 (*outptr++) = 256 - repcount;    /* count */
  116.                 (*outptr++) = data;        /* value */
  117.  
  118.                 /* Now pop to the top of the loop 
  119.                  * looking for more repeat counts.
  120.                  */
  121.  
  122.                 continue; /* top of loop */
  123.             }
  124.  
  125.             /* Special case.  If we have arrived at this point,
  126.              * then repcount is now equal to 0.  This means
  127.              * that when we entered this section, repcount
  128.              * was a multiple of 128 (i.e. 128 :-).
  129.              *
  130.              * This means that there were 129 identical bytes,
  131.              * so the output does a replicate of 127 which
  132.              * gives 128 bytes, and we now have one byte left
  133.              * over which should NOT be output as a repeat
  134.              * run, rather it should be merged into the following
  135.              * literal run (if it exists).
  136.              *
  137.              * So, we will simply fall thru to the next section
  138.              * of code which assumes that we are working on 
  139.              * a literal run.
  140.              */
  141.         }
  142.  
  143.         /* Literal run.  At this point, the current data byte
  144.          * does NOT match the following byte.  We will transfer
  145.          * these non-identical bytes until:
  146.          *
  147.          *      1)  we run out of input data (count == 0).
  148.          *      2)  we run out of room in this output block (128)
  149.          *      3)  we come across a value which occurs at least
  150.          *          three times in a row.  A value occuring only
  151.          *          twice in a row does NOT justify dropping
  152.          *          out of a literal run.
  153.          *
  154.          * Special case:  If we run out of room in the output block
  155.          * (which is 128 bytes), the last two values are the same,
  156.          * AND there is more input, it makes sense to restart
  157.          * the repeat detector in case the following bytes are
  158.          * repeats of the two.  A simple check of the following
  159.          * byte will determine this.
  160.          * (This case falls out with the test for triples below).
  161.          *
  162.          * Special case:  If we run out of room in the output block
  163.          * (which is 128 bytes), the last value is the same as
  164.          * the next one on the input, then it is better to let
  165.          * that byte be used in a possible replicate run following
  166.          * the literal run.  If the last byte matches ONLY the
  167.          * following byte, (and not the one after that, it is
  168.          * a wash, but for best results, we will test the
  169.          * following two bytes.
  170.          */
  171.  
  172.         litcount = 0;
  173.         saveptr = outptr++;    /* save location of the command byte */
  174.  
  175.         if(outptr + 1 > last)
  176.             return(-1);
  177.  
  178.         (*outptr++) = data;    /* save the first byte. */
  179.  
  180.         lastbyte = data;    /* remember for testing */
  181.  
  182.         while(count > 0 && litcount < 127)
  183.         {
  184.             data = (*inptr++);
  185.             count--;
  186.             litcount++;
  187.  
  188.             if(outptr + 1 > last)
  189.                 return(-1);
  190.  
  191.             (*outptr++) = data;
  192.  
  193.             /* Test to see if this byte matched the last one.
  194.              * If so, check the next one for a triple.
  195.              */
  196.             if(lastbyte == data && count > 0 && (*inptr) == data)
  197.             {
  198.                 /* We have a triple, adjust accordingly.
  199.                  * Add two bytes back onto the input.
  200.                  */
  201.  
  202.                 count += 2;
  203.                 inptr -= 2;
  204.                 outptr -= 2;
  205.                 litcount -= 2;
  206.  
  207.                 break; /* out of loop */
  208.             }
  209.  
  210.             lastbyte = data; /* save data byte */
  211.         }
  212.  
  213.         /* Check the special case number 2 above. */
  214.         if(litcount == 127 && count > 1 && data == (*inptr) && data == inptr[1])
  215.         {
  216.             /*  Restore the last byte to the input stream */
  217.             count += 1;
  218.             inptr -= 1;
  219.             outptr -= 1;
  220.             litcount -= 1;
  221.         }
  222.  
  223.         /* Save the literal run count. */
  224.         (*saveptr) = litcount;
  225.     }
  226.  
  227.     return(outptr - dest);
  228. }
  229.